﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CodeTunnel.MvcUtilities.Components
{
    /// <summary>
    /// Base controller that ensures that the X-Requested-With header is preserved across redirects.
    /// Note: Firefox contains a bug that does not forward this header across redirects.
    /// This class is need if you want to use Request.IsAjaxRequest() in your controllers and views.
    /// </summary>
    public class AjaxHeaderPreservationController : Controller
    {
        #region -= FireFox Redirect Fix =-

        /// <summary>
        /// 
        /// </summary>
        private string _X_Requested_With_Header = "X-Requested-With";

        /// <summary>
        /// Checks TempData for stored header value. If there is a value and Request.IsAjaxRequest()
        /// is false then it adds the value from TempData to the request headers. This ensures future
        /// calls to Request.IsAjaxRequest() behave appropriately.
        /// </summary>
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var ajaxHeader = TempData[_X_Requested_With_Header] as string;
            if (!Request.IsAjaxRequest() && ajaxHeader != null)
                Request.Headers.Add(_X_Requested_With_Header, ajaxHeader);
        }

        /// <summary>
        /// After action executes we check to see if a redirect result is being returned. If so, then
        /// we store the value of the X-Requested-With header in TempData to be read back after the
        /// redirect.
        /// </summary>
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            if (Request.IsAjaxRequest() && IsRedirectResult(filterContext.Result))
                TempData[_X_Requested_With_Header] = Request.Headers[_X_Requested_With_Header];
        }

        /// <summary>
        /// Identifies if an ActionResult's type contains the word "Redirect".
        /// </summary>
        private bool IsRedirectResult(ActionResult result)
        {
            return result.GetType().Name.ToUpper().Contains("REDIRECT");
        }

        #endregion
    }
}